package com.zhouyu;

import com.zhouyu.nine.OrderService;
import com.zhouyu.nine.UserMulConstructorService;
import com.zhouyu.nine.UserService;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanNameReference;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.function.Supplier;

/**
 * https://www.yuque.com/books/share/5f19528d-d89b-4b69-a7bd-9f436a2dd734/te9peg
 */
public class Test09 {
	public static void main(String[] args) {

		/**
		 * Supplier
		 */
		/*AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
		GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
		beanDefinition.setBeanClass(OrderService.class);
		beanDefinition.setInstanceSupplier(
				new Supplier<Object>() {
					@Override
					public Object get() {
						OrderService service = new OrderService();
						System.out.println(service);
						return service;
					}
				}
		);


		context.registerBeanDefinition(OrderService.class.getSimpleName(),beanDefinition);
		context.refresh();
		OrderService orderService = context.getBean("OrderService", OrderService.class);
		System.out.println(orderService);*/

		/**
		 * 只有一个有参数的构造方法, 会根据构造方法的参数去找bean
		 */
		/*AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig09.class);
		UserService userService = (UserService) context.getBean("userService");
		userService.test();*/

		/*ClassPathXmlApplicationContext context1 = new ClassPathXmlApplicationContext("spring09.xml");
		UserService userService1 = (UserService) context1.getBean("userService");
		userService1.test();*/

		/**
		 * 多个构造方法的操作
		 * 1. 如果开发者指定了想要使用的构造方法，那么就用这个构造方法
		 *    还有开发者指定想要使用的构造方法 一种是 xml操作 ，一种是在构造方法上增加 Autowired
		 * 2. 如果开发者没有指定想要使用的构造方法，则看开发者有没有让Spring自动去选择构造方法
		 * 	  这一点只能用到 ClassPathXmlApplicationContext 中 ,会自动选择构造方法中参数最多的！！！
		 * 3. 如果开发者也没有让Spring自动去选择构造方法，则Spring利用无参构造方法，如果没有无参构造方法，则报错
		 */
		/*AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig09.class);
		UserMulConstructorService userMulConstructorService = (UserMulConstructorService) context.getBean("userMulConstructorService");
		userMulConstructorService.test();*/

		/*ClassPathXmlApplicationContext context1 = new ClassPathXmlApplicationContext("spring09.xml");
		UserMulConstructorService userMulConstructorService = (UserMulConstructorService) context1.getBean("userMulConstructorService");
		userMulConstructorService.test();*/

		/**
		 * 用户自定义传的参数 调用构造方法
		 */
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig09.class);
		/*UserMulConstructorService userMulConstructorService = (UserMulConstructorService) context.getBean("userMulConstructorService", new OrderService(), new OrderService());
		userMulConstructorService.test();*/

		/**
		 * 使用自己设置的方式 调用某个构造方法
		 */
		/*AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
		beanDefinition.setBeanClass(UserMulConstructorService.class);
		beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(1,new OrderService());
		//另外一种方式的传值方式
		beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(1,new RuntimeBeanNameReference("orderService"));
		//这一段注释掉的话会报错
//		beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
		context.registerBeanDefinition("userMulConstructorService",beanDefinition);

		UserMulConstructorService userMulConstructorService = (UserMulConstructorService) context.getBean("userMulConstructorService");
		userMulConstructorService.test();*/

		/**
		 * LookUp 注解使用 查看Test04
		 *
		 */


	}
}
